package com.mvc.servlet;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mvc.anno.*;

public class DispathServlet extends HttpServlet {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	/**
	 * 所有.class文件名  com.mvc.controller.MvxController.class
	 */
	private List<String> classNames = new ArrayList<>();
	/**
	 * 所有加注解的bean
	 */
	private HashMap<String, Object> beans = new HashMap<>();
	/**
	 * url对应的method
	 */
	private HashMap<String, Method> handlerMap = new HashMap<>();//路径映射

	
	/* (non-Javadoc)
	 * @see javax.servlet.GenericServlet#init()
	 * 初始化容器 实例化bean urlmapping
	 */
	@Override
	public void init() throws ServletException {
		// TODO Auto-generated method stub
		scanPackage("com.mvc"); //获取所有class文件
		doInstance(); //实例化  new MvxController()
		doAutowrited(); //实现注入
		
		urlMapping(); // 所有url对应的Method
	}
	
	
	/**
	 * mapping映射
	 * http到method
	 */
	private void urlMapping() {
		// TODO Auto-generated method stub
		for (Entry<String, Object> entry : beans.entrySet()) {
			Object instance = entry.getValue();
			Class<? extends Object> clazz = instance.getClass();
			if(clazz.isAnnotationPresent(SelfController.class)) {
				String url1 = clazz.getAnnotation(SelfRequestMappping.class).value();
				Method[] methods = clazz.getMethods();//获取到所有方法
				for (Method method : methods) {
					if(method.isAnnotationPresent(SelfRequestMappping.class)) {
						String url2 = method.getAnnotation(SelfRequestMappping.class).value();	
						handlerMap.put(url1+url2, method);
					}else {
						continue;
					}
				}
			}
		}
	}
				


	/**
	 * 依赖注入
	 */
	private void doAutowrited() {
		// TODO Auto-generated method stub
		for (Entry<String, Object> entry : beans.entrySet()) {
			try {
			Object instance = entry.getValue();
			if(instance.getClass().isAnnotationPresent(SelfController.class)) {
				 Field[] fields = instance.getClass().getDeclaredFields();
				 for (Field field : fields) {
					 if(field.isAnnotationPresent(SelfAutowrited.class)) {
						 String key = field.getAnnotation(SelfAutowrited.class).value();
						 field.setAccessible(true);
						 field.set(instance, beans.get(key));
					 }else {
						continue;
					}
				}
			}  else {
				continue;
			} 
			} catch (  SecurityException | IllegalArgumentException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}


	/**
	 * 实例化，存入bean
	 */
	private void doInstance() {
		// TODO Auto-generated method stub
		for (String cname : classNames) {
			String replace = cname.replace(".class", "");
			try {
				Class<?> forName = Class.forName(replace);
				if(forName.isAnnotationPresent(SelfController.class)) {//处理controller修饰的类
					Object newInstance = forName.newInstance();
					String key = forName.getAnnotation(SelfRequestMappping.class).value();
					beans.put(key, newInstance);
 				}else if (forName.isAnnotationPresent(SelfService.class)) {
 					Object newInstance = forName.newInstance();
					String key = forName.getAnnotation(SelfService.class).value();
					beans.put(key, newInstance);
				}else {
					continue;
				}
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}


	/**
	 * @param scanPackage
	 * 获取到所有class文件
	 */
	private void scanPackage(String scanPackage) {
		// TODO Auto-generated method stub
		String fp = "/"+scanPackage.replaceAll("\\.", "/");
		URL url = this.getClass().getResource(fp);
		String strFile = url.getFile();
		File[] files = new File(strFile).listFiles();
		for (File f : files) {
			if(f.isDirectory()) { //文件夾
				this.scanPackage(scanPackage+"."+f.getName());
			}else {//文件
				classNames.add(scanPackage+"."+f.getName());
			}
		}
	}


	/* (non-Javadoc)
	 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 *  业务请求相关代码
	 */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		this.doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// TODO Auto-generated method stub
		String uri = req.getRequestURI(); //   /项目名/mvc/hello
		String contextPath = req.getContextPath(); //项目名
		String path = uri.replace(contextPath, "");
		Object object = beans.get("/"+path.split("/")[1]);
		if(object == null) {
			return;
		}
		Method method = handlerMap.get(path);
		if(method == null) {
			return;
		}

		String value=null;
		for (Annotation[] parameterAnnotation : method.getParameterAnnotations()) {
			for (Annotation annotation : parameterAnnotation) {
				if(annotation  instanceof  SelfRequestParam){
					SelfRequestParam  selfRequestParam= (SelfRequestParam) annotation;
					value = selfRequestParam.value();
				}
			}
		}

		try {
			method.invoke( object, req,resp,value);
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
